/*
** Test Tile Map by Neil C. Obremski                          [ Magenta's Maze ]
** 2017 Gibdon Moon Productions                   [ http://magsmaze.gibdon.com ]
**
** This is free and unencumbered software released into the public domain.
**
** Anyone is free to copy, modify, publish, use, compile, sell, or
** distribute this software, either in source code form or as a compiled
** binary, for any purpose, commercial or non-commercial, and by any
** means.
**
** In jurisdictions that recognize copyright laws, the author or authors
** of this software dedicate any and all copyright interest in the
** software to the public domain. We make this dedication for the benefit
** of the public at large and to the detriment of our heirs and
** successors. We intend this dedication to be an overt act of
** relinquishment in perpetuity of all present and future rights to this
** software under copyright law.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
** OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
** OTHER DEALINGS IN THE SOFTWARE.
**
** Tested w/ DOSBox 0.74, Microsoft C 5.10
 */
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <math.h>

#include "mag-cga.h"
#include "mag-bios.h"
#include "mag-math.h"
#include "mag-inp.h"

#include "mag-3d.h"		/* need CGA before including */

/* models */
#include "mag-cube.h"
#include "mag-tree.h"

#include "mag-map.h"
#include "mag-puzz.h"

int main(int argc, char *argv[])
{
	int i, x, y;
	int act = 0;
	char TREE_TILE;
	unsigned char far *dbuf = _fmalloc(0x4000);
	unsigned char far *scrn = cga_vbuf;
	char doublebuffer = FALSE;
	int oldmode = 3;
	int turning = 0, turndir = 0;
	int moving = 0, moveinc = 0;
	char project3d = TRUE;
	#ifndef NDEBUG
	char *codepart = "";
	unsigned char *safemem = malloc(sizeof(SIN_FX));
	memcpy(safemem, SIN_FX, sizeof(SIN_FX));
	#endif

	init3d();
	initmap();

	for (i = 1; i <= 9; i++) {
		tile_cube((char)i, FALSE);
	}

	TREE_TILE = tile_tree(FALSE);

	if (argc < 2 || !loadmap(argv[1])) {
		puzzle(argc < 2 ? "PUZZLE" : argv[1], TREE_TILE);
	}

	oldmode = screen(4);

	if (doublebuffer) {
		cga_vbuf = dbuf;
	}

	do {
		#ifndef NDEBUG
		codepart = "ACTION";
		if (0 != memcmp(safemem, SIN_FX, sizeof(SIN_FX))) {
			break;
		}
		#endif

		if (ACT_UP == act) {			/* up */
			move(FALSE);
		} else if (ACT_LEFT == act) {	/* left */
			turnleft(TRUE);
		} else if (ACT_RIGHT == act) {	/* right */
			turnright(TRUE);
		} else if (ACT_USE == act) {	/* enable/disable 3D */
			project3d = project3d ? FALSE : TRUE;
		}

		#ifndef NDEBUG
		codepart = "MOVEorTURN";
		if (0 != memcmp(safemem, SIN_FX, sizeof(SIN_FX))) {
			break;
		}
		#endif

		clearpipe(TRUE);		/* clear 3D pipeline */

		cls(BLACK);
		#ifndef NDEBUG
		codepart = "CLS";
		if (0 != memcmp(safemem, SIN_FX, sizeof(SIN_FX))) {
			break;
		}
		#endif

		for (y = 0; y < MAP_H; y++) {
			for (x = 0; x < MAP_W; x++) {
				if (map[y][x]) {
					boxfill(x*5, y*5, x*5+4, y*5+4,
						TREE_TILE == map[y][x] ? CYAN : MAGENTA);
				}
			}
		}

		viewmap();				/* view map (add objects to pipeline) */
		viewmagic();

		#ifndef NDEBUG
		codepart = "VIEWMAP";
		if (0 != memcmp(safemem, SIN_FX, sizeof(SIN_FX))) {
			break;
		}
		#endif

		arrow(pos.x*5+2, pos.y*5+2, pos.facing, 2, MAGENTA);
		if (project3d) {
			circley3d(0,-50,100,30,MAGENTA);
			drawmagic();
			pipeline(TRUE, TRUE, TRUE); /* process 3D pipeline */
		}

		#ifndef NDEBUG
		codepart = "PIPELINE";
		if (0 != memcmp(safemem, SIN_FX, sizeof(SIN_FX))) {
			break;
		}
		#endif

		if (doublebuffer) {
			blit(320, 200, dbuf, scrn);
			if (project3d) {
				locate(23,0);
				printf("%2d,%2d @ %d%c (%c)", pos.x, pos.y, pos.facing,
					(char)248, rnext);
			}
		}

		#ifndef NDEBUG
		codepart = "BLIT";
		if (0 != memcmp(safemem, SIN_FX, sizeof(SIN_FX))) {
			break;
		}
		#endif

	} while (!((act = action(TRUE)) & ACT_ESC));

	if (doublebuffer) {
		cga_vbuf = scrn;
	}

	screen(oldmode);

	for (i = 0; i < rsize; i++) {
		printf("R %02d/%02d: %c%c (%d,%d)\n", 1+i, rsize,
			rpipe[i]->mdl, rpipe[i]->cid,
			rpipe[i]->mdl, rpipe[i]->cid);
	}

	printf("Tile Size: %d x %d = %d\n", sizeof(struct tile), TILE_MAX,
		sizeof(tiles));

	quit3d();
	_ffree(dbuf);
	#ifndef NDEBUG
	{
		unsigned char *sp = safemem + sizeof(SIN_FX) - 1,
			*rp = (unsigned char *)(SIN_FX) + sizeof(SIN_FX) - 1;
		int ei = 0, i = 0;
		for ( ; i < sizeof(SIN_FX); i++) {
			if (*sp-- != *rp--) {
				ei = (sizeof(SIN_FX) - i - 1);
				break;
			}
		}
		if (ei) {
			sp = safemem;
			rp = (unsigned char*)(SIN_FX);
			for (i = 0; i < sizeof(SIN_FX); i++) {
				if (*sp++ != *rp++) {
					printf("MEMORY CORRUPTION after %s (%d - %d)\n",
						codepart, i, ei);
					break;
				}
			}
		}
	}
	/* if (0 != memcmp(safemem, SIN_FX, sizeof(SIN_FX))) {
		printf("MEMORY CORRUPTION!\n");
	} */
	free(safemem);
	#endif

	return 0;
}
